#ifndef _COROUTINE_H_
#define _COROUTINE_H_

#include <iostream>  // 用于输入输出操作
#include <memory>    // 用于智能指针管理
#include <atomic>    // 用于原子操作
#include <functional> // 用于定义和操作函数对象
#include <cassert>   // 用于断言操作
#include <ucontext.h> // 用于上下文切换
#include <unistd.h>  // 用于操作系统接口
#include <mutex>     // 用于线程互斥锁

namespace zsylar {

class Fiber : public std::enable_shared_from_this<Fiber>
// std::enable_shared_from_this 的主要作用是允许一个类的实例安全地创建指向自身的 std::shared_ptr。
// 可以通过 shared_from_this() 方法获取一个指向该实例的 std::shared_ptr。
{
public:
    // 协程的状态
    enum State
    {
        READY,    // 准备就绪
        RUNNING,  // 正在运行
        TERM      // 已终止
    };

private:
    // 仅由GetThis()调用->私有->创建主协程
    Fiber();

public:
    // 构造函数，接受一个函数对象、可选的栈大小和是否运行在调度器中
    Fiber(std::function<void()> cb, size_t stacksize = 0, bool run_in_scheduler = true);
    // 析构函数
    ~Fiber();

    // 重用一个协程
    void reset(std::function<void()> cb);

    // 任务线程恢复执行
    void resume();
    // 任务协程让出执行权（暂停执行）
    void yield();

    uint64_t getId() const { return m_id; }
    State getState() const { return m_state; }

public:
    // 设置当前运行协程
    static void SetThis(Fiber* f);
    // 得到当前运行的协程
    static std::shared_ptr<Fiber> GetThis();
    // 设置调度协程（默认为主协程）
    static void SetSchedulerFiber(Fiber* f);
    // 得到当前运行的协程id
    static uint64_t GetFiberId();
    // 协程函数
    static void MainFunc();

private:
    uint64_t m_id = 0;          // 协程ID
    uint32_t m_stacksize = 0;   // 协程栈大小
    State m_state = READY;      // 协程状态
    ucontext_t m_ctx;           // 协程上下文
    void* m_stack = nullptr;    // 协程栈指针
    std::function<void()> m_cb; // 协程函数执行对象
    bool m_runInScheduler = false; // 是否在调度器中运行

public:
    std::mutex m_mutex; // 互斥锁，用于保护协程的状态
}; 

}

#endif